package com.cmcc.cmii.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.alibaba.fastjson.util.FieldInfo;
import com.alibaba.fastjson.util.TypeUtils;
import com.dslplatform.json.DslJson;
import com.dslplatform.json.runtime.Settings;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.lang.reflect.Array;
import java.sql.Timestamp;
import java.util.*;

/**
 * *********************************
 *
 * @ClassName: JsonUtil.java
 * @Description: JSON序列化
 * @author: Thanks
 * @createdAt: 2018-12-11下午04:46:54
 **********************************
 */
public class JsonUtil {
    /**
     * 默认的序列化参数
     */
    private final static SerializerFeature[] DEFAULT_FEATURES = { SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullListAsEmpty,
            // SerializerFeature.WriteNullNumberAsZero,
            SerializerFeature.WriteNullBooleanAsFalse, SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteDateUseDateFormat };
    /**
     * 默认配置
     */
    private static SerializeConfig DEFALULT_MAPPING = new SerializeConfig();

    static {
        DEFALULT_MAPPING.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd"));
        DEFALULT_MAPPING.put(Timestamp.class, new SimpleDateFormatSerializer("yyyy-MM-dd"));
    }

    /**
     *
     * <p>
     * Title:
     * </p>
     * <p>
     * Description:
     * </p>
     */
    private JsonUtil() {

    }

    /**
     *
     * @Title: toJSONString
     * @Description: javabean 序列化成 JSON
     * @param obj
     *            obj
     * @param features
     *            features
     * @return String
     * @Author: bieby
     * @Date: 2018-12-7
     */
    public static String toJSONString(Object obj, SerializerFeature... features) {
        return JSON.toJSONString(obj, DEFALULT_MAPPING,
                (SerializerFeature[]) ArrayUtils.addAll(DEFAULT_FEATURES, features));
    }

    /**
     *
     * @Title: toJSONString
     * @Description: javabean 序列化成 JSON
     * @param obj
     *            obj
     * @param features
     *            features
     * @param mapping
     *            mapping
     * @return value
     * @Author: bieby
     * @Date: 2013-12-7
     */
    public static String toJSONString(Object obj, SerializeConfig mapping, SerializerFeature... features) {
        return JSON.toJSONString(obj, mapping, (SerializerFeature[]) ArrayUtils.addAll(DEFAULT_FEATURES, features));
    }

    /**
     *
     * @Title: parseArray
     * @Description: json 序列化list
     * @param batchParams
     *            batchParams
     * @param cls
     *            cls
     * @return json 序列化list
     * @Author: bieby
     * @Date: 2013-12-11
     */
    public static <T> List<T> parseArray(String batchParams, Class<T> cls) {
        if (StringUtils.isNotEmpty(batchParams) && !"[]".equals(batchParams)) {
            return JSON.parseArray(batchParams, cls);
        } else {
            return new ArrayList<T>();
        }
    }

    /**
     *
     * @Title: getMapFromJson @Description: json 转换成MAP 只支持1级json
     * {'TABLENAME':'PROVIDER','TYPE':'provider'} @param jsonString
     * jsonString @return @return Map<String,Object> @throws
     */
    public static final Map<String, Object> getMapFromJson(String jsonString) {
        if (StringUtils.isBlank(jsonString)) {
            return new HashMap<String, Object>();
        }
        Map<String, Object> jsonMap = (Map<String, Object>) JSONObject.parseObject(jsonString);
        return jsonMap;
    }

    /**
     *
     * getModelFromJson:把json数据转换成自定义对象. <br/>
     *
     * @author ibm
     * @param <T>
     * @param jsonString
     * @param clazz
     * @return
     * @since JDK 1.8
     */
    public static final <T> Object getModelFromJson(String jsonString, Class<T> clazz) {
        if (StringUtils.isBlank(jsonString)) {
            return null;
        }
        return JSONObject.parseObject(jsonString, clazz);
    }

    /**
     * DSL-json parse JsonString to Model blue
     *
     * @param jsonData
     * @param clazz
     * @param <T>
     * @return
     */
    public static final <T> Object getModelFromDSLjson(String jsonData, Class<T> clazz) {
        Object obj = new Object();
        try {
            DslJson.Settings settings = Settings.withRuntime() // Runtime configuration needs to be explicitly enabled
                    .includeServiceLoader(); // for java8 types
            DslJson<Object> json = new DslJson(settings);
            byte[] bytes = jsonData.getBytes("UTF-8");
            InputStream stream = new ByteArrayInputStream(bytes);
            obj = json.deserialize(clazz, stream); // will use thread local reader
        } catch (IOException e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * DSL-json covert Model to JsonString
     *
     * @param obj
     * @return
     */

    public static final String getDSLjsonFromModel(Object obj) {
        String jsonData = "";
        try {
            DslJson.Settings settings = Settings.withRuntime().includeServiceLoader();
            DslJson<Object> json = new DslJson(settings);
            OutputStream outputStream = new ByteArrayOutputStream();
            json.serialize(obj, outputStream);
            jsonData = outputStream.toString();
        } catch (IOException var7) {
            var7.printStackTrace();
        }
        return jsonData;
    }

    public static String javaObject2JsonObject(Object obj) {
        return JSON.toJSONString(obj);
    }

    // 重写JSON.toJSON方法 luohongd 20160329 如果存在子段的类型为String的值为null那么反回空""
    public static final Object toJSON(Object javaObject) {
        return toJSON(javaObject, ParserConfig.getGlobalInstance());
    }

    public static final Object toJSON(Object javaObject, ParserConfig mapping) {
        if (javaObject == null) {
            return null;
        }

        if ((javaObject instanceof JSON)) {
            return (JSON) javaObject;
        }

        if ((javaObject instanceof Map)) {
            Map<String, Object> map = (Map) javaObject;
            JSONObject json = new JSONObject(map.size());

            for (Map.Entry entry : map.entrySet()) {
                Object key = entry.getKey();
                String jsonKey = TypeUtils.castToString(key);
                Object jsonValue = toJSON(entry.getValue());
                json.put(jsonKey, jsonValue);
            }
            return json;

        }

        if ((javaObject instanceof Collection)) {
            Collection collection = (Collection) javaObject;
            JSONArray array = new JSONArray(collection.size());

            for (Iterator i$ = collection.iterator(); i$.hasNext();) {
                Object item = i$.next();
                Object jsonValue = toJSON(item);
                array.add(jsonValue);
            }
            return array;
        }

        Class clazz = javaObject.getClass();

        if (clazz.isEnum()) {
            return ((Enum) javaObject).name();
        }
        if (clazz.isArray()) {
            int len = Array.getLength(javaObject);
            JSONArray array = new JSONArray(len);
            for (int i = 0; i < len; i++) {
                Object item = Array.get(javaObject, i);
                Object jsonValue = toJSON(item);
                array.add(jsonValue);
            }
            return array;
        }

        if (mapping.isPrimitive(clazz)) {
            return javaObject;
        }
        try {
            List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);

            JSONObject json = new JSONObject(getters.size());

            for (FieldInfo field : getters) {
                Object value = field.get(javaObject);
                Object jsonValue = toJSON(value);
                if (value == null) {
                    if ((field.getFieldType().toString()).contains("class java.lang.String")) {
                        jsonValue = "";
                    }
                }

                json.put(field.getName(), jsonValue);

            }
            return json;
        } catch (Exception e) {
            throw new JSONException("toJSON error", e);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> Map<String, Object> json2map(String jsonStr) throws Exception {
        return JSON.parseObject(jsonStr, Map.class);
    }

    public static <T> T map2obj(Map<?, ?> map, Class<T> clazz) throws Exception {
        return JSON.parseObject(JSON.toJSONString(map), clazz);
    }

    public static void main(String[] args) {
        // String json = "{\"id\":\"444\",\"name\":\"zhou智能\"}";
        // UserTest user = (UserTest) getModelFromJson(json, UserTest.class);
        // System.out.println("22");
    }

}
